package alpha.com.google.code.mechanic.janitor.ui;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;

import org.eclipse.core.databinding.beans.PojoObservables;
import org.eclipse.core.databinding.observable.map.IObservableMap;
import org.eclipse.core.databinding.observable.set.IObservableSet;
import org.eclipse.core.databinding.property.Properties;
import org.eclipse.jface.databinding.viewers.ObservableMapLabelProvider;
import org.eclipse.jface.databinding.viewers.ObservableSetContentProvider;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.viewers.CheckStateChangedEvent;
import org.eclipse.jface.viewers.CheckboxTableViewer;
import org.eclipse.jface.viewers.ICheckStateListener;
import org.eclipse.jface.viewers.TableViewerColumn;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.DirectoryDialog;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.Text;

import alpha.com.google.code.mechanic.janitor.model.IContext;

/**
 *
 * The class is to let users specify the configuration files of which Contexts
 * they need to export, and export them to which directory. At the end, all
 * the configuration files will be compressed and named as Context_Name.zip
 * files.
 * 
 * Last_edited: Oct 29, 2014
 *
 * @author jingjiejiang
 * @since Oct 15, 2014
 */
public class ExportContextDialog extends Dialog {
  
  //The title of the dialog.
  private static final String EXPORT_CONTEXT_DIALOG_TITLE = "Export Context Settings";
  
  private Table tableContexts;
  private CheckboxTableViewer chkTblContexts;
  private Button btnSelAll;
  private Button btnDeselAll;
  private Button btnDstnDir;
  
  private Set<IContext> contexts;
  private Text txtDstnDir;
  private List<IContext> selContexts;
  private String strDstnDir;

  /**
   * Create the dialog.
   * @param parentShell
   */
  public ExportContextDialog(Shell parentShell, Set<IContext> setContext) {
    super(parentShell);
    
    contexts = setContext;
    selContexts = new ArrayList<IContext>();
  }
  
  public String getDstnDir() {
    return strDstnDir;
  }
  
  public List<IContext> getSelContexts() {
    return selContexts;
  }
  
  @Override
  public void create() {
    super.create();
    getButton(IDialogConstants.OK_ID).setEnabled(false);
  }
  
  @Override
  public void configureShell (Shell shell) {
    super.configureShell(shell);
    if (EXPORT_CONTEXT_DIALOG_TITLE != null) {
      shell.setText(EXPORT_CONTEXT_DIALOG_TITLE);
    }
  }

  /**
   * Create contents of the dialog.
   * @param parent
   */
  @Override
  protected Control createDialogArea(Composite parent) {
    Composite container = (Composite) super.createDialogArea(parent);
    
    Composite composite = new Composite(container, SWT.NONE);
    GridData gd_composite = new GridData(SWT.LEFT, SWT.CENTER, false, false, 1, 1);
    gd_composite.heightHint = 282;
    gd_composite.widthHint = 414;
    composite.setLayoutData(gd_composite);
    
    initChkTblContexts(composite);
    initBtnSelAll(composite);
    initBtnDeselAll(composite);
    
    initBtnDstnDir(composite);
    
    Label lblContexts = new Label(composite, SWT.NONE);
    lblContexts.setBounds(0, 0, 59, 14);
    lblContexts.setText("Contexts:");
    
    Label lblExportTo = new Label(composite, SWT.NONE);
    lblExportTo.setBounds(0, 233, 59, 14);
    lblExportTo.setText("Export to:");
    
    initTxtDstnDir(composite);
    
    initDataBindings();
    
    return container;
  }
  
  private void initTxtDstnDir (Composite composite) {
    
    txtDstnDir = new Text(composite, SWT.BORDER);
    txtDstnDir.setEditable(false);
    txtDstnDir.addModifyListener(new ModifyListener() {
      public void modifyText(ModifyEvent e) {
        
        updateOkBtnStatus();
      }
    });
    txtDstnDir.setBounds(0, 253, 365, 19);
  }
  
  /**
   * The method is to update the status of the "OK" button. If there exists
   * selected Contexts and the destination directory is not null, then enable
   * the "OK" button; otherwise disable it.
   *
   */
  private void updateOkBtnStatus() {
    
    boolean enableOKBtn = false;
    Object[] obejcts = chkTblContexts.getCheckedElements();
    
    if (0 != obejcts.length && !txtDstnDir.getText().equals("")) {
      enableOKBtn = true;
    }

    getButton(IDialogConstants.OK_ID).setEnabled(enableOKBtn);
  }
  
  private void initBtnDstnDir (Composite composite) {
    
    btnDstnDir = new Button(composite, SWT.NONE);
    btnDstnDir.addSelectionListener(new SelectionAdapter() {
      @Override
      public void widgetSelected(SelectionEvent e) {
        
        DirectoryDialog dialog = new DirectoryDialog(getParentShell());
        String path = dialog.open();
        txtDstnDir.setText(path);
      }
    });
    btnDstnDir.setBounds(371, 249, 43, 28);
    btnDstnDir.setText("...");
  }
  
  private void initBtnDeselAll (Composite composite) {
    
    btnDeselAll = new Button(composite, SWT.NONE);
    btnDeselAll.addSelectionListener(new SelectionAdapter() {
      @Override
      public void widgetSelected(SelectionEvent e) {
        chkTblContexts.setAllChecked(false);
        updateOkBtnStatus();
      }
    });
    btnDeselAll.setBounds(100, 199, 94, 28);
    btnDeselAll.setText("Deselect All");
  }
  
  private void initBtnSelAll (Composite composite) {
    
    btnSelAll = new Button(composite, SWT.NONE);
    btnSelAll.addSelectionListener(new SelectionAdapter() {
      @Override
      public void widgetSelected(SelectionEvent e) {
        chkTblContexts.setAllChecked(true);
        updateOkBtnStatus();
      }
    });
    btnSelAll.setBounds(0, 199, 94, 28);
    btnSelAll.setText("Select All");
  }
  
  private void initChkTblContexts (Composite composite) {
    
    chkTblContexts = CheckboxTableViewer.newCheckList(composite, SWT.BORDER | SWT.FULL_SELECTION);
    chkTblContexts.addCheckStateListener(new ICheckStateListener() {
      public void checkStateChanged(CheckStateChangedEvent event) {
        
        updateOkBtnStatus();
      }
    });
    tableContexts = chkTblContexts.getTable();
    tableContexts.setHeaderVisible(true);
    tableContexts.setBounds(0, 20, 414, 169);
    
    TableViewerColumn tblClmnCtxName = new TableViewerColumn(chkTblContexts, SWT.NONE);
    TableColumn clmnCtxName = tblClmnCtxName.getColumn();
    clmnCtxName.setWidth(400);
    clmnCtxName.setText("      Name");
  }

  /**
   * Create contents of the button bar.
   * @param parent
   */
  @Override
  protected void createButtonsForButtonBar(Composite parent) {
    createButton(parent, IDialogConstants.OK_ID, IDialogConstants.OK_LABEL,
        true);
    createButton(parent, IDialogConstants.CANCEL_ID,
        IDialogConstants.CANCEL_LABEL, false);
  }

  /**
   * Return the initial size of the dialog.
   */
  @Override
  protected Point getInitialSize() {
    return new Point(433, 374);
  }

  protected void initDataBindings() {
    
    ObservableSetContentProvider setContentProvider = new ObservableSetContentProvider();
    IObservableMap observeMap = PojoObservables.observeMap(setContentProvider.getKnownElements(), IContext.class, "name");
    chkTblContexts.setLabelProvider(new ObservableMapLabelProvider(observeMap));
    chkTblContexts.setContentProvider(setContentProvider);
    IObservableSet selfSet = Properties.selfSet(IContext.class).observe(contexts);
    chkTblContexts.setInput(selfSet);
  }
  
  @Override
  public void okPressed() {
    
    strDstnDir = txtDstnDir.getText();
    getSelContext();
    
    super.okPressed();
  }

  private void getSelContext() {
    
    Object[] objects = chkTblContexts.getCheckedElements();
    for (Object object: objects) {
      
      selContexts.add((IContext)object);
    }
  }
  
}
